/**
 * 
 */
package t4j.concurrency;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import t4j.net.mindview.util.BasicGenerator;
import t4j.net.mindview.util.Generator;

//生产者
class ExchangerProducer<T> implements Runnable {

	private Generator<T> generator;
	private Exchanger<List<T>> exchanger;
	private List<T> holder;
	
	public ExchangerProducer(Exchanger<List<T>> exchg, Generator<T> gen, List<T> holder) {
		exchanger = exchg;
		generator = gen;
		this.holder = holder;
	}

	@Override
	public void run() {
		try {
			while (!Thread.interrupted()) {
				for (int i = 0; i < ExchangerDemo.size; i++)
					holder.add(generator.next());//创建对象，放进list里,每次增加10个
				
				holder = exchanger.exchange(holder);//把list放进交互,如果另外一个线程不执行接收，则会阻塞在这里
				
				System.out.println("end add");
			}
		} catch (InterruptedException e) {}

	}

}

//消费者
class ExchangeConsumer<T> implements Runnable {
	private Exchanger<List<T>> exchanger;
	private List<T> holder;
	private volatile T value;

	public ExchangeConsumer(Exchanger<List<T>> ex, List<T> holder) {
		exchanger = ex;
		this.holder = holder;
	}

	@Override
	public void run() {
		
		int count = 1;
		
		try {
			while (!Thread.interrupted()) {
				
				holder = exchanger.exchange(holder);//接收另外一个线程的list，如果没有，则阻塞在这里等待

				for (T x : holder) {
					value = x;
					holder.remove(x);
					System.out.println(value);
				}
			}
		} catch (InterruptedException e) {}

		System.out.println("Final value: " + value);
	}

}

public class ExchangerDemo {
	static int size = 10;
	static int delay = 3;

	public static void main(String[] args) throws Exception {
		
		ExecutorService exec = Executors.newCachedThreadPool();
		
		Exchanger<List<Fat>> xc = new Exchanger<List<Fat>>();

		List<Fat> producerList = new CopyOnWriteArrayList<Fat>()
				, consumerList = new CopyOnWriteArrayList<Fat>();

		exec.execute(new ExchangerProducer<Fat>(xc, BasicGenerator.create(Fat.class), producerList));

		exec.execute(new ExchangeConsumer<Fat>(xc, consumerList));

		TimeUnit.SECONDS.sleep(delay);

		exec.shutdownNow();
	}
}
